import * as Minio from 'minio';
import { Client, ClientOptions } from 'minio';
import { BadRequestException, HttpException } from '@nestjs/common';
const Fs = require('fs')

const allMinio = {
    arktao: {
        endPoint: 'localhost',
        port: 9999,
        accessKey: 'minioadmin',
        secretKey: 'minioadmin',
        useSSL: false
    }
}

export class MinioClient {
    minioClient: Client;
    config: ClientOptions
    constructor() {
        this.config = allMinio["arktao"]
        this.minioClient = new Minio.Client({
            ...this.config
        });
    }
    async makeBucket(data) {
        return this.minioClient.makeBucket(data.bucketName, 'cn-north-1').then(() => {
            return 'Bucket created successfully'
        }).catch(err => {
            throw new BadRequestException(err)
        })
    }
    async listBuckets() {
        return this.minioClient.listBuckets().then((res) => {
            return res
        }).catch(err => {
            throw new BadRequestException(err)
        })
    }
    async bucketExists(name) {
        return this.minioClient.bucketExists(name).then((res) => {
            if (!res) return "bucket does not exist."
            return res
        }).catch(err => {
            throw new BadRequestException(err)
        })
    }
    async removeBucket(name) {
        return this.minioClient.removeBucket(name).then((res) => {
            return 'Bucket removed successfully.'
        }).catch(err => {
            throw new BadRequestException(err)
        })
    }
    async listObjects(name) {
        return new Promise(resolve => {
            const stream = this.minioClient.listObjects(name, '', true)
            let list = []
            stream.on('data', function (obj) {
                list.push(obj)
            })
            stream.on('error', function (err) { console.log(err) })
            stream.on('end', function () {
                resolve(list)
            })
        })
    }
    async listIncompleteUploads(name) {
        return new Promise(resolve => {
            const stream = this.minioClient.listIncompleteUploads(name, '', true)
            let list = []
            stream.on('data', function (obj) {
                list.push(obj)
            })
            stream.on('error', function (err) { console.log(err) })
            stream.on('end', function () {
                resolve(list)
            })
        })
    }
    async putObject(file, body) {
        return new Promise(resolve => {
            this.minioClient.putObject(body.bucketName, body.objectName, file.buffer, file.size, function (err, etag) {
                if (err) throw new BadRequestException(err)
                resolve(body.objectName)
            })
        })
    }
    async getObject(bucketName, objectName) {
        return await this.minioClient.getObject(bucketName, objectName)
    }
    getObjectUrl(bucketName, objectName): string {
        return this.config.useSSL ? 'https://' : 'http://' + this.config.endPoint + ':' + this.config.port + '/' + bucketName + '/' + objectName
    }
    //下载并将对象保存成本地文件。
    async fGetObject(bucketName, objectName, filePath): Promise<void> {
        return new Promise(resolve => {
            this.minioClient.fGetObject(bucketName, objectName, filePath, function (err) {
                if (err) throw new BadRequestException(err)
                resolve()
            })
        })
    }
    async putObject2(file, body) {
        return new Promise(resolve => {
            const fileStream = Fs.createReadStream(file)
            this.minioClient.putObject(body.bucketName, body.objectName, fileStream, function (err, etag) {
                if (err) throw new BadRequestException(err)
                resolve(body.objectName)
            })
        })
    }
    async copyObject(body) {
        return new Promise(resolve => {
            const conds = new Minio.CopyConditions()
            conds.setMatchETag(body.etag)
            this.minioClient.copyObject(body.bucketName, body.objectName, body.sourceObject, null, function (err, data) {
                if (err) throw new BadRequestException(err)
                resolve(data)
            })
        })
    }
    async statObject(body) {
        return new Promise(resolve => {
            this.minioClient.statObject(body.bucketName, body.objectName, function (err, stat) {
                if (err) throw new BadRequestException(err)
                resolve(stat)
            })
        })
    }
    async removeObject(body) {
        return new Promise(resolve => {
            this.minioClient.removeObject(body.bucketName, body.objectName, function (err) {
                if (err) throw new BadRequestException(err)
                resolve('Removed the object')
            })
        })
    }
}
